/**
 * 组件通信
 *  1. 父组件 -> 子组件
 *      props
 *  2. 子组件 -> 父组件
 *      props
 *      父组件传递一个函数给子组件，子组件调用该函数且可以传递参数过来
 *  3. 兄弟组件之间
 *      1. 状态提升，找到共同的父组件，将数据存放在父组件上，然后通过 props 传递给这两个兄弟。
 *  5. 关系复杂组件之间
 *      1. Context 上下文
 *      2. 事件总线的方式。
 *        mitt
 *        tiny-emitter
 *        pubsub-js
 *      3. 状态管理器
 *        Flux
 *        Redux
 *        mobx
 *        ...
 *  6. ref 获取子组件的实例对象的方式。
 *
 */

import React from "react";

// 引入 pubsub-js
import PubSub from "pubsub-js";

// 订阅
const token = PubSub.subscribe("abcd", (message, data) => {
  // 回调函数的第一个参数是消息名字
  //         第二个参数才是触发这个消息时传递过来的参数
  console.log("abcd 被触发了", message, data);
});

// 发布
setTimeout(() => {
  PubSub.publish("abcd", "张三");
}, 1000);

// 取消订阅
PubSub.unsubscribe(token);

// Hello 组件
function Hello(props) {
  console.log("Hello Props", props);
  return (
    <div>
      <h4>Hello - {props.name}</h4>
      <button onClick={() => props.fn("李四")}>
        点我，修改父组件name为李四
      </button>

      <button onClick={() => props.fn("王五")}>
        点我，修改父组件name为王五
      </button>

      <button onClick={() => props.fn()}>点我，修改父组件name</button>
    </div>
  );
}
// Hello.contextType = MyContext;

// App 组件
class App extends React.Component {
  state = {
    name: "张三",
  };

  changeName = (name) => {
    console.log("changeName", name);
    this.setState({
      name: name ? name : this.state.name + "~",
    });
  };

  render() {
    return (
      <div>
        <h1>App</h1>
        <hr />
        <Hello name={this.state.name} fn={this.changeName} />
      </div>
    );
  }
}

export default App;
